package org.example.java.classloader;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

/**
 * this class show Difference between thread's context class loader and normal classloader (http://stackoverflow.com/questions/1771679/difference-between-threads-context-class-loader-and-normal-classloader)
 *
 * URLClassLoader does not load class (http://stackoverflow.com/questions/18850403/why-urlclassloader-does-not-load-class)
 *  dir must end with '/'
 *
 * @author juntao zhang
 */
public class ContextClassLoaderTest {

  public static void main(String[] args) throws MalformedURLException, ClassNotFoundException {
    System.out.println("MainClass getClassLoader: " + ContextClassLoaderTest.class.getClassLoader());
    System.out.println("MainClass getContextClassLoader: " + Thread.currentThread().getContextClassLoader());
    try {
      Class clazz = ContextClassLoaderTest.class.getClassLoader().loadClass("Hello");
      System.out.println(clazz.newInstance());
    } catch (Exception e) {
      e.printStackTrace();
    }
    Thread innerThread1 = new InnerThread1();
    innerThread1.start();
  }

}

class InnerThread1 extends Thread {
  @Override
  public void run() {
    try {
      URLClassLoader urlClassLoader = URLClassLoader.newInstance(new URL[]{new File("hello/").toURI().toURL()});
      Class<?> clazz = urlClassLoader.loadClass("Hello");
      System.out.println(clazz.newInstance());

      System.out.println("InnerThread1 getClassLoader: " + clazz.getClassLoader());
      System.out.println("InnerThread1 getContextClassLoader: " + Thread.currentThread().getContextClassLoader());

      this.setContextClassLoader(urlClassLoader);

      Thread innerThread2 = new InnerThread2();
      innerThread2.start();
    } catch (MalformedURLException | ClassNotFoundException | IllegalAccessException | InstantiationException e) {
      e.printStackTrace();
    }
  }
}


class InnerThread2 extends Thread {
  @Override
  public void run() {
    try {
      ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
      classLoader.loadClass("Hello");
      System.out.println("InnerThread2 getClassLoader: " + this.getClass().getClassLoader());
      System.out.println("InnerThread2 getContextClassLoader: " + Thread.currentThread().getContextClassLoader());
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    }
  }
}
